/*

Summary:
A writer priority lock for sharing resource between threads.

Remark:
WARNING, this class isn't been tested well. It may has some 
potential problems.

The algorithm being used is from Liu DongNing, who is a great
teacher in GDUT. Thanks for him.

The algorithm is listed below.

Writer:
P(writable)
	if (writeCount == 0) P(Readable)
	++writecCount;
V(writable)
P(Wmutex)
	Do something for write...
V(Wmutex)
P(writable)
	--writeCount
	if (writeCount == 0) V(Readable)
V(writable)

Reader:
P(readable)
P(Rmutex)
	if (readCount == 0) P(Wmutex)
	++readCount
V(Rmutex)
V(readable)
	Do something for read...
P(Rmutex)
	--readCount
	if (readCount == 0) V(Wmutex)
V(Rmutex)

Version:
0.0.2

LastUpdatedDate:
2012-09-06

CreatedDate:
2012-09-04

*/

#pragma once

#include <Windows.h>


namespace Zaf {
namespace Sync {


class WriterPriorityLock {

public:
	WriterPriorityLock();
	~WriterPriorityLock();

	void ReaderEnter();
	void WriterEnter();

	void ReaderLeave();
	void WriterLeave();

private:
	WriterPriorityLock(const WriterPriorityLock&);
	const WriterPriorityLock& operator=(const WriterPriorityLock&);

	void P(HANDLE mutex) {
		WaitForSingleObject(mutex, INFINITE);
	}

	void V(HANDLE mutex) {
		ReleaseSemaphore(mutex, 1, nullptr);
	}

	DWORD m_readerCount;
	DWORD m_writerCount;

	HANDLE m_readerCountLock;
	HANDLE m_writerCountLock;

	HANDLE m_writeLock;
	HANDLE m_readLock;
};


}
}